home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library / Microsoft Programmer's Library (CD-ROM Database)(125-099-008)(Version 1.1a)(CDRM 162100)(1989).iso / SAMPCODE / OS2SDK11 / TK4 / LINEFRAC / LFCMD.C < prev    next >
C/C++ Source or Header  |  1989-02-20  |  35KB  |  1,428 lines

  1. /************************************************************************
  2. *
  3. *   lfcmd.c -- Subroutines for menu command processing for LineFractal.
  4. *
  5. *   Created by Microsoft Corporation, 1989
  6. *
  7. ************************************************************************/
  8.  
  9. #define INCL_WIN
  10. #define INCL_GPI
  11. #define INCL_BITMAPFILEFORMAT
  12. #define INCL_DOSSEMAPHORES
  13. #define INCL_DOSMEMMGR
  14. #define INCL_DOSPROCESS
  15. #include <os2.h>
  16.  
  17. #include <mt\stdio.h>
  18. #include <mt\stdlib.h>
  19. #include <mt\math.h>
  20.  
  21. #include "opendlg.h"
  22.  
  23. #define INCL_GLOBALS
  24. #define INCL_THREADS
  25. #include "linefrac.h"
  26.  
  27. #define INCL_LFCMD
  28. #define INCL_LFDLG
  29. #define INCL_LFMAIN
  30. #define INCL_LFTHREAD
  31. #define INCL_LFPS
  32. #define INCL_LFDRAW
  33. #define INCL_LFUTIL
  34. #define INCL_LFFILE
  35. #include "lffuncs.h"
  36.  
  37.  
  38.  
  39.  
  40. /************************************************************************
  41. *
  42. *   Macros
  43. *
  44. *   Helper macros for repetitious code.
  45. *
  46. ************************************************************************/
  47.  
  48. #define UPDATE_MENU_BOOL(var, val)                \
  49.     {                            \
  50.         TOGGLE_BOOL((var));                 \
  51.         TOGGLE_MENU_ITEM(global.hwndFrame, (val), (var));    \
  52.     }
  53.  
  54. #define UPDATE_MENU_LIST(var, val)                \
  55.     {                            \
  56.         UNCHECK_MENU_ITEM(global.hwndFrame, (var));     \
  57.         (var) = (val);                    \
  58.         CHECK_MENU_ITEM(global.hwndFrame, (var));        \
  59.     }
  60.  
  61.  
  62.  
  63.  
  64. /************************************************************************
  65. *
  66. *   Global Variables
  67. *
  68. *   global    Global data block.
  69. *   aulRops    Array of BitBlt rops available for pasting.
  70. *   aXform    Array of built-in transforms and default positioning
  71. *          and sizing information.
  72. *
  73. ************************************************************************/
  74.  
  75. extern GLOBALDATA global;
  76. extern XFORMDATA  aXform[];
  77.  
  78. ULONG aulRops[] =
  79. {
  80.       ROP_SRCCOPY,
  81.       ROP_SRCAND,
  82.       ROP_SRCPAINT,
  83.       ROP_SRCINVERT,
  84.     (~ROP_SRCCOPY)   & 0xFF,
  85.     (~ROP_SRCAND)    & 0xFF,
  86.     (~ROP_SRCPAINT)  & 0xFF,
  87.     (~ROP_SRCINVERT) & 0xFF
  88. };
  89.  
  90. char *pszAttrs = "Previous attributes not read yet.";
  91.  
  92.  
  93.  
  94.  
  95. /************************************************************************
  96. *
  97. *   LfCommand
  98. *
  99. *   Dispatches menu commands to the proper handlers.
  100. *
  101. ************************************************************************/
  102.  
  103. VOID
  104. LfCommand(hwnd, id)
  105. HWND hwnd;
  106. USHORT id;
  107. {
  108.     switch (id)
  109.     {
  110.  
  111.     /********************************************************************
  112.     *
  113.     *    File menu
  114.     *
  115.     ********************************************************************/
  116.  
  117.     case IDM_LOAD:
  118.     case IDM_SAVE:
  119.     case IDM_ABOUT:
  120.     LfFileMenu(hwnd, id);
  121.     break;
  122.  
  123.     /********************************************************************
  124.     *
  125.     *    Edit menu
  126.     *
  127.     ********************************************************************/
  128.  
  129.     case IDM_SELECT:
  130.     case IDM_SELECTALL:
  131.     case IDM_CUT:
  132.     case IDM_COPY:
  133.     case IDM_PASTE:
  134.     case IDM_USECLIPBRD:
  135.     case IDM_PASTES:
  136.     case IDM_PASTEDSA:
  137.     case IDM_PASTEDSO:
  138.     case IDM_PASTEDSX:
  139.     case IDM_PASTESN:
  140.     case IDM_PASTEDSAN:
  141.     case IDM_PASTEDSON:
  142.     case IDM_PASTEDSXN:
  143.     LfEditMenu(hwnd, id);
  144.     break;
  145.  
  146.     /********************************************************************
  147.     *
  148.     *    Thread menu
  149.     *
  150.     ********************************************************************/
  151.  
  152.     case IDM_DCPOSTSCRIPT:
  153.     case IDM_DCPROPRINTER:
  154.     case IDM_DCDIRECT:
  155.     case IDM_DCMEMORY:
  156.     case IDM_EDITTHREADPARAMS:
  157.     case IDM_THR0TOTOP:
  158.     case IDM_THR1TOTOP:
  159.     case IDM_THR2TOTOP:
  160.     case IDM_THR3TOTOP:
  161.     case IDM_THR4TOTOP:
  162.     case IDM_THR5TOTOP:
  163.     case IDM_THR6TOTOP:
  164.     case IDM_THR7TOTOP:
  165.     case IDM_THR8TOTOP:
  166.     case IDM_THR9TOTOP:
  167.     case IDM_KILLTOPTHREAD:
  168.     case IDM_KILLALLTHREADS:
  169.     case IDM_AUTOSWITCH:
  170.     case IDM_SWITCHDELAY:
  171.     case IDM_UPDATEMENUS:
  172.     case IDM_THREADINHERITANCE:
  173.     LfThreadMenu(hwnd, id);
  174.     break;
  175.  
  176.     /********************************************************************
  177.     *
  178.     *    Control menu
  179.     *
  180.     ********************************************************************/
  181.  
  182.     case IDM_CLEARBITMAP:
  183.     case IDM_COPYBITMAPTOSCREEN:
  184.     case IDM_SQUAREBITMAP:
  185.     case IDM_RESIZEBITMAPTOWINDOW:
  186.     case IDM_MOUSECHANGESRECURSION:
  187.     case IDM_ANIMATEPTR:
  188.     case IDM_PTRPREFERENCES:
  189.     case IDM_TIMERDELAY:
  190.     if (LfControlMenu(hwnd, id))
  191.         goto lfcmd_redraw;
  192.     break;
  193.  
  194.     /********************************************************************
  195.     *
  196.     *    Fractal menu
  197.     *
  198.     ********************************************************************/
  199.  
  200.     case IDM_SHARKTOOTH:
  201.     case IDM_SAWTOOTH:
  202.     case IDM_KOCH:
  203.     case IDM_SPACEFILLER:
  204.     case IDM_STOVE:
  205.     case IDM_SQUAREWAVE:
  206.     case IDM_HOURGLASS:
  207.     case IDM_FRACREDRAW:
  208.     if (LfFractalMenu(hwnd, id))
  209.         goto lfcmd_redraw;
  210.     break;
  211.  
  212.     /********************************************************************
  213.     *
  214.     *    Primitive menu
  215.     *
  216.     ********************************************************************/
  217.  
  218.     case IDM_POLYLINE:
  219.     case IDM_POLYFILLET:
  220.     case IDM_POLYSPLINE:
  221.     case IDM_POLYMARKER:
  222.     case IDM_PEANO:
  223.     case IDM_PRIMREDRAW:
  224.     if (LfPrimitiveMenu(hwnd, id))
  225.         goto lfcmd_redraw;
  226.     break;
  227.  
  228.     /********************************************************************
  229.     *
  230.     *    Attributes menu
  231.     *
  232.     ********************************************************************/
  233.  
  234.     case IDM_LINEATTRS:
  235.     case IDM_MARKERATTRS:
  236.     case IDM_AREAATTRS:
  237.     case IDM_IMAGEATTRS:
  238.     case IDM_MISCATTRS:
  239.     case IDM_DIMENSIONS:
  240.     case IDM_DRAGDIMS:
  241.     case IDM_ATTRREDRAW:
  242.     if (LfAttributesMenu(hwnd, id))
  243.         goto lfcmd_redraw;
  244.     break;
  245.  
  246.     /********************************************************************
  247.     *
  248.     *    Environment menu
  249.     *
  250.     ********************************************************************/
  251.  
  252.     case IDM_AUTORESIZE:
  253.     case IDM_AUTOSELECTDIMS:
  254.     case IDM_CLEARONREDRAW:
  255.     case IDM_AUTOSTARTREDRAW:
  256.     case IDM_COLLECTBOUNDS:
  257.     LfEnvironmentMenu(hwnd, id);
  258.     break;
  259.  
  260.     /********************************************************************
  261.     *
  262.     *    Control menu, continued.  These two commands dovetail
  263.     *    conveniently,  so they are placed out of sequence here.
  264.     *
  265.     ********************************************************************/
  266.  
  267. lfcmd_redraw:
  268.     case IDM_REDRAW:
  269.     DosSemClear(&(global.pThrTop)->lSemRedraw);
  270.  
  271.     /* Fall through to restart the drawing. */
  272.  
  273.     case IDM_ABORT:
  274.     global.pThrTop->fInterrupted = TRUE;
  275.     break;
  276.     }
  277. }
  278.  
  279.  
  280.  
  281.  
  282. /************************************************************************
  283. *
  284. *   LfFileMenu
  285. *
  286. *   These commands allow the loading and saving of bitmaps from threads
  287. *   with memory DC's.  The about box shows the version number, title,
  288. *   and author.
  289. *
  290. ************************************************************************/
  291.  
  292. VOID
  293. LfFileMenu(hwnd, id)
  294. HWND hwnd;
  295. USHORT id;
  296. {
  297.     switch (id)
  298.     {
  299.     case IDM_LOAD:
  300.     if (global.pThrTop->dcType == IDM_DCMEMORY)
  301.         LfReadFile(hwnd, global.pThrTop);
  302.     else
  303.         MyMessageBox(hwnd, "Cannot load bitmap into a\nnon-memory DC.");
  304.     break;
  305.  
  306.     case IDM_SAVE:
  307.     if (global.pThrTop->dcType == IDM_DCMEMORY)
  308.         LfWriteFile(hwnd, global.pThrTop);
  309.     else
  310.         MyMessageBox(hwnd, "Cannot save bitmap from a\nnon-memory DC.");
  311.     break;
  312.  
  313.     case IDM_ABOUT:
  314.     WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)AboutDlg, NULL,
  315.                IDR_ABOUTDLG, NULL );
  316.     break;
  317.     }
  318. }
  319.  
  320.  
  321.  
  322.  
  323. /************************************************************************
  324. *
  325. *   LfEditMenu
  326. *
  327. *   These commands allow for cutting, copying, and pasting of rectangles
  328. *   of bits.  The user can drag a rectangle or select the entire surface.
  329. *   The GpiBitBlt rop to use when pasting can be any of those listed.
  330. *   The user can specify that the system clipboard be used for storing
  331. *   the cut or copied bits, or that a private bitmap be used.
  332. *
  333. ************************************************************************/
  334.  
  335. VOID
  336. LfEditMenu(hwnd, id)
  337. HWND hwnd;
  338. USHORT id;
  339. {
  340.     switch (id)
  341.     {
  342.     case IDM_SELECT:
  343.     global.fSelecting = TRUE;
  344.     break;
  345.  
  346.     case IDM_SELECTALL:
  347.     LfSelectAll(hwnd);
  348.     break;
  349.  
  350.     case IDM_CUT:
  351.     if (global.fShowSelectRc)
  352.         LfCut(hwnd);
  353.     break;
  354.  
  355.     case IDM_COPY:
  356.     if (global.fShowSelectRc)
  357.         LfCopy(hwnd);
  358.     break;
  359.  
  360.     case IDM_PASTE:
  361.     if (global.fHaveSelectRc)
  362.     {
  363.         HPS hps;
  364.  
  365.         global.fPasting = TRUE;
  366.         if (global.fShowSelectRc && global.fTempSelect)
  367.         {
  368.         hps = WinGetPS(hwnd);
  369.         LfShowSelectRc(hps, &global.rclSelect);
  370.         WinReleasePS(hps);
  371.         global.fShowSelectRc = FALSE;
  372.         global.fTempSelect = FALSE;
  373.         }
  374.         if (!global.fShowSelectRc)
  375.         {
  376.         global.fShowSelectRc = TRUE;
  377.         hps = WinGetPS(hwnd);
  378.         LfShowSelectRc(hps, &global.rclCutCopy);
  379.         WinReleasePS(hps);
  380.         }
  381.     }
  382.     break;
  383.  
  384.     case IDM_USECLIPBRD:
  385.     UPDATE_MENU_BOOL(global.fUseClipbrd, IDM_USECLIPBRD);
  386.     break;
  387.  
  388.     /********************************************************************/
  389.  
  390.     case IDM_PASTES:
  391.     case IDM_PASTEDSA:
  392.     case IDM_PASTEDSO:
  393.     case IDM_PASTEDSX:
  394.     case IDM_PASTESN:
  395.     case IDM_PASTEDSAN:
  396.     case IDM_PASTEDSON:
  397.     case IDM_PASTEDSXN:
  398.     UNCHECK_MENU_ITEM(global.hwndFrame, global.usRopIndex+IDM_PASTES);
  399.     global.usRopIndex = id - IDM_PASTES;
  400.     CHECK_MENU_ITEM(global.hwndFrame, global.usRopIndex+IDM_PASTES);
  401.     global.ulPasteROP = aulRops[global.usRopIndex];
  402.     break;
  403.     }
  404. }
  405.  
  406.  
  407.  
  408.  
  409. /************************************************************************
  410. *
  411. *   LfThreadMenu
  412. *
  413. *   These commands allow the creation, viewing, editing, and deletion
  414. *   of up to 10 independently drawing threads.    The middle group
  415. *   allow for simple animation by cycling through the threads at
  416. *   a user-selectable rate.  The updating of menus can be disabled to
  417. *   allow a faster thread-switch rate.    The last group determine how
  418. *   new threads will look and act.  If inheritance is enabled, a new
  419. *   thread will be drawn with the attributes of the top thread, otherwise
  420. *   it will use the program's default values.
  421. *
  422. ************************************************************************/
  423.  
  424. VOID
  425. LfThreadMenu(hwnd, id)
  426. HWND hwnd;
  427. USHORT id;
  428. {
  429.     static char *szError1 = "Could not start thread.";
  430.  
  431.     switch (id)
  432.     {
  433.     case IDM_DCPOSTSCRIPT:
  434.     case IDM_DCPROPRINTER:
  435.     break;    /* not implemented yet */
  436.  
  437.     case IDM_DCDIRECT:
  438.     {
  439.         PTHR pthr;
  440.  
  441.         if (global.cThr < MAX_THREADS)
  442.         if (pthr = LfStartThread(IDM_DCDIRECT))
  443.         {
  444.             (global.aThr)[global.cThr] = pthr;
  445.             ++global.cThr;
  446.             pthr->dcType = id;
  447.  
  448.             LfBringThreadToTop(pthr);
  449.             break;
  450.         }
  451.         MyMessageBox(hwnd, szError1);
  452.     }
  453.     break;
  454.  
  455.     case IDM_DCMEMORY:
  456.  
  457.     if (global.cThr < MAX_THREADS)
  458.     {
  459.         if (global.fFirstThread)
  460.         {
  461.         global.bm.cx        = (USHORT) (global.rcl.xRight - global.rcl.xLeft);
  462.         global.bm.cy        = (USHORT) (global.rcl.yTop   - global.rcl.yBottom);
  463.         global.bm.cPlanes   = 0;
  464.         global.bm.cBitCount = 0;
  465.         global.fFirstThread = FALSE;
  466.         }
  467.         else if (global.fThreadInheritance)
  468.         {
  469.         global.bm.cx        = (USHORT) global.pThrTop->rcl.xRight;
  470.         global.bm.cy        = (USHORT) global.pThrTop->rcl.yTop;
  471.         global.bm.cPlanes   = global.pThrTop->cPlanes;
  472.         global.bm.cBitCount = global.pThrTop->cBitCount;
  473.         }
  474.         else
  475.         {
  476.         global.bm.cx        = (USHORT) (global.rcl.xRight - global.rcl.xLeft);
  477.         global.bm.cy        = (USHORT) (global.rcl.yTop   - global.rcl.yBottom);
  478.         global.bm.cPlanes   = 0;
  479.         global.bm.cBitCount = 0;
  480.         if (!WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)BitmapParamsDlg, NULL,
  481.                    IDR_BITMAPPARAMSDLG, NULL ))
  482.             break;    /* if user hit "cancel", don't start thread */
  483.         }
  484.  
  485.         {
  486.         PTHR pthr;
  487.  
  488.         if (pthr = LfStartThread(IDM_DCMEMORY))
  489.         {
  490.             (global.aThr)[global.cThr] = pthr;
  491.             ++global.cThr;
  492.             pthr->dcType = id;
  493.  
  494.             LfBringThreadToTop(pthr);
  495.             break;
  496.         }
  497.         }
  498.     }
  499.     MyMessageBox(hwnd, szError1);
  500.     break;
  501.  
  502.     case IDM_EDITTHREADPARAMS:
  503.     if (global.pThrTop->dcType == IDM_DCMEMORY)
  504.     {
  505.         USHORT cxT, cyT, cpT, cbT;
  506.  
  507.         cxT = global.bm.cx          = (USHORT) global.pThrTop->rcl.xRight;
  508.         cyT = global.bm.cy          = (USHORT) global.pThrTop->rcl.yTop;
  509.         cpT = global.bm.cPlanes   = global.pThrTop->cPlanes;
  510.         cbT = global.bm.cBitCount = global.pThrTop->cBitCount;
  511.  
  512.         if (WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)BitmapParamsDlg, NULL,
  513.                IDR_BITMAPPARAMSDLG, NULL ))
  514.         if ((cxT != global.bm.cx)      ||
  515.             (cyT != global.bm.cy)      ||
  516.             (cpT != global.bm.cPlanes) ||
  517.             (cbT != global.bm.cBitCount))
  518.             LfResizePS(global.pThrTop);
  519.     }
  520.     else
  521.         MyMessageBox(hwnd, "No editable DC parameters.");
  522.     break;
  523.  
  524.     case IDM_THR0TOTOP:
  525.     case IDM_THR1TOTOP:
  526.     case IDM_THR2TOTOP:
  527.     case IDM_THR3TOTOP:
  528.     case IDM_THR4TOTOP:
  529.     case IDM_THR5TOTOP:
  530.     case IDM_THR6TOTOP:
  531.     case IDM_THR7TOTOP:
  532.     case IDM_THR8TOTOP:
  533.     case IDM_THR9TOTOP:
  534.     {
  535.         USHORT i;
  536.  
  537.         if ((i = id-IDM_THR0TOTOP) < global.cThr)
  538.         LfBringThreadToTop(global.aThr[i]);
  539.     }
  540.     break;
  541.  
  542.     case IDM_KILLTOPTHREAD:
  543.     {
  544.         PTHR pthr;
  545.  
  546.         pthr = global.pThrTop;
  547.         if (global.cThr > 1)
  548.         {
  549.         SHORT i;
  550.  
  551.         if ((i = global.iThrTop+1) == global.cThr)
  552.             i -= 2;
  553.         LfBringThreadToTop(global.aThr[i]);
  554.         }
  555.         else
  556.         LfBringThreadToTop(NULL);
  557.  
  558.         LfKillThread(pthr);
  559.         LfBringThreadToTop(global.pThrTop);     /* update global.iThrTop and menu */
  560.  
  561.         /* If no threads left, then start over. */
  562.         if (global.cThr == 0)
  563.         {
  564.         global.fFirstThread = TRUE;
  565.         WinSendMsg(hwnd, WM_COMMAND, (MPARAM)IDM_DCMEMORY, 0);
  566.         }
  567.     }
  568.     break;
  569.  
  570.     case IDM_KILLALLTHREADS:
  571.     {
  572.         SHORT i;
  573.  
  574.         /* Delete them all and start over. */
  575.         LfBringThreadToTop(NULL);
  576.         for (i = global.cThr-1; i >= 0; --i)
  577.         LfKillThread(global.aThr[i]);
  578.         global.fFirstThread = TRUE;
  579.         WinSendMsg(hwnd, WM_COMMAND, (MPARAM)IDM_DCMEMORY, 0);
  580.     }
  581.     break;
  582.  
  583.     /********************************************************************/
  584.  
  585.     case IDM_AUTOSWITCH:
  586.     UPDATE_MENU_BOOL(global.fAutoSwitch, IDM_AUTOSWITCH);
  587.     if (global.fAutoSwitch)
  588.         WinStartTimer(global.hab, global.hwnd, IDT_AUTOSWITCH, global.usSwitchDelay);
  589.     else
  590.         WinStopTimer(global.hab, global.hwnd, IDT_AUTOSWITCH);
  591.     break;
  592.  
  593.     case IDM_SWITCHDELAY:
  594.     WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)SwitchDelayDlg, NULL,
  595.                IDR_SWITCHDELAYDLG, NULL );
  596.     break;
  597.  
  598.     case IDM_UPDATEMENUS:
  599.     UPDATE_MENU_BOOL(global.fUpdateMenusOnThreadSwitch, IDM_UPDATEMENUS);
  600.     break;
  601.  
  602.     /********************************************************************/
  603.  
  604.     case IDM_THREADINHERITANCE:
  605.     UPDATE_MENU_BOOL(global.fThreadInheritance, IDM_THREADINHERITANCE);
  606.     break;
  607.  
  608.     }
  609. }
  610.  
  611.  
  612.  
  613.  
  614. /************************************************************************
  615. *
  616. *   LfControlMenu
  617. *
  618. *   These commands cause global effects.  The top set cause immediate
  619. *   results.  The bottom set determine how the program reacts to
  620. *   certain events (mouse movement and button messages, timer messages).
  621. *
  622. ************************************************************************/
  623.  
  624. BOOL
  625. LfControlMenu(hwnd, id)
  626. HWND hwnd;
  627. USHORT id;
  628. {
  629.     BOOL fRedraw = FALSE;
  630.  
  631.     switch (id)
  632.     {
  633.     case IDM_CLEARBITMAP:
  634.     LfClearRect(global.pThrTop, NULL);
  635.     break;
  636.  
  637.     case IDM_COPYBITMAPTOSCREEN:
  638.     if (global.pThrTop->hps)
  639.         WinInvalidateRect(global.hwnd, &(global.pThrTop)->rcl, FALSE);
  640.     break;
  641.  
  642.     case IDM_SQUAREBITMAP:
  643.     LfSquareBitmap(hwnd);
  644.     break;
  645.  
  646.     case IDM_RESIZEBITMAPTOWINDOW:
  647.     LfResizeBitmapToWindow();
  648.     fRedraw = TRUE;
  649.     break;
  650.  
  651.     /********************************************************************/
  652.  
  653.     case IDM_MOUSECHANGESRECURSION:
  654.     UPDATE_MENU_BOOL(global.fMouseChangesRecursion, IDM_MOUSECHANGESRECURSION);
  655.     break;
  656.  
  657.     case IDM_ANIMATEPTR:
  658.     UPDATE_MENU_BOOL(global.fAnimatePtr, IDM_ANIMATEPTR);
  659.     if (global.fAnimatePtr)
  660.         global.usPtrIncr = 1;
  661.     else
  662.     {
  663.         global.usPtrIncr = 0;
  664.         global.usCurPtr  = global.usUserPtr;
  665.     }
  666.     break;
  667.  
  668.     case IDM_PTRPREFERENCES:
  669.     WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)PtrPreferencesDlg, NULL,
  670.                IDR_PTRPREFERENCESDLG, NULL );
  671.     break;
  672.  
  673.     case IDM_TIMERDELAY:
  674.     WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)TimerDelayDlg, NULL,
  675.                IDR_TIMERDELAYDLG, NULL );
  676.     break;
  677.     }
  678.  
  679.     return fRedraw;
  680. }
  681.  
  682.  
  683.  
  684.  
  685. /************************************************************************
  686. *
  687. *   LfFractalMenu
  688. *
  689. *   These commands select the fractal similarity transform, i.e. the
  690. *   basic fractal shape, for a thread.
  691. *
  692. ************************************************************************/
  693.  
  694. BOOL
  695. LfFractalMenu(hwnd, id)
  696. HWND hwnd;
  697. USHORT id;
  698. {
  699.     BOOL fRedraw = FALSE;
  700.  
  701.     switch (id)
  702.     {
  703.     case IDM_SHARKTOOTH:
  704.     case IDM_SAWTOOTH:
  705.     case IDM_KOCH:
  706.     case IDM_SPACEFILLER:
  707.     case IDM_STOVE:
  708.     case IDM_SQUAREWAVE:
  709.     case IDM_HOURGLASS:
  710.     LfSelectXform(hwnd, global.pThrTop, id);
  711.     if (global.pThrTop->fFracRedraw)
  712.         fRedraw = TRUE;
  713.     break;
  714.  
  715.     /********************************************************************/
  716.  
  717.     case IDM_FRACREDRAW:
  718.     UPDATE_MENU_BOOL(global.pThrTop->fFracRedraw, IDM_FRACREDRAW);
  719.     break;
  720.     }
  721.  
  722.     return fRedraw;
  723. }
  724.  
  725.  
  726.  
  727.  
  728. /************************************************************************
  729. *
  730. *   LfPrimitiveMenu
  731. *
  732. *   These commands select the drawing primitive used to output the
  733. *   fractal for a thread.
  734. *
  735. ************************************************************************/
  736.  
  737. BOOL
  738. LfPrimitiveMenu(hwnd, id)
  739. HWND hwnd;
  740. USHORT id;
  741. {
  742.     BOOL fRedraw = FALSE;
  743.  
  744.     switch (id)
  745.     {
  746.     case IDM_POLYLINE:
  747.     case IDM_POLYFILLET:
  748.     case IDM_POLYSPLINE:
  749.     case IDM_POLYMARKER:
  750.     case IDM_PEANO:
  751.     LfSelectPrim(hwnd, global.pThrTop, id);
  752.     if (global.pThrTop->fPrimRedraw)
  753.         fRedraw = TRUE;
  754.     break;
  755.  
  756.     /********************************************************************/
  757.  
  758.     case IDM_PRIMREDRAW:
  759.     UPDATE_MENU_BOOL(global.pThrTop->fPrimRedraw, IDM_PRIMREDRAW);
  760.     break;
  761.     }
  762.  
  763.     return fRedraw;
  764. }
  765.  
  766.  
  767.  
  768.  
  769. /************************************************************************
  770. *
  771. *   LfAttributesMenu
  772. *
  773. *   These commands allow the user to alter all the drawing attributes
  774. *   of a fractal (color, mix mode, marker symbol, etc.), as well as
  775. *   some fractal-related attributes such as width, height, offset,
  776. *   number of sides to polygonal frame, and rotation.  Each thread
  777. *   has an independent set of all these attributes.
  778. *
  779. ************************************************************************/
  780.  
  781. BOOL
  782. LfAttributesMenu(hwnd, id)
  783. HWND hwnd;
  784. USHORT id;
  785. {
  786.     BOOL fRedraw = FALSE;
  787.  
  788.     switch (id)
  789.     {
  790.     case IDM_LINEATTRS:
  791.     if (global.fUpdateAttrs && (global.flLineAttrs & LFA_LINEALL))
  792.         MyMessageBox(hwnd, pszAttrs);
  793.     if (WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)LineAttrsDlg, NULL,
  794.                IDR_LINEATTRSDLG, NULL ))
  795.         fRedraw = TRUE;
  796.     break;
  797.  
  798.     case IDM_MARKERATTRS:
  799.     if (global.fUpdateAttrs && (global.flMarkerAttrs & LFA_MARKALL))
  800.         MyMessageBox(hwnd, pszAttrs);
  801.     if (WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)MarkerAttrsDlg, NULL,
  802.                IDR_MARKERATTRSDLG, NULL ))
  803.         fRedraw = TRUE;
  804.     break;
  805.  
  806.     case IDM_AREAATTRS:
  807.     if (global.fUpdateAttrs && (global.flAreaAttrs & LFA_AREAALL))
  808.         MyMessageBox(hwnd, pszAttrs);
  809.     if (WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)AreaAttrsDlg, NULL,
  810.                IDR_AREAATTRSDLG, NULL ))
  811.         fRedraw = TRUE;
  812.     break;
  813.  
  814.     case IDM_IMAGEATTRS:
  815.     if (global.fUpdateAttrs && (global.flImageAttrs & LFA_IMAGEALL))
  816.         MyMessageBox(hwnd, pszAttrs);
  817.     if (WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)ImageAttrsDlg, NULL,
  818.                IDR_IMAGEATTRSDLG, NULL ))
  819.         fRedraw = TRUE;
  820.     break;
  821.  
  822.     case IDM_MISCATTRS:
  823.     if (global.fUpdateAttrs && (global.flMiscAttrs & (LFA_RECURSION |
  824.         LFA_CPTMAX | LFA_POLYGONSIDES | LFA_ROTATION)))
  825.         MyMessageBox(hwnd, pszAttrs);
  826.     if (WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)MiscAttrsDlg, NULL,
  827.                IDR_MISCATTRSDLG, NULL ))
  828.         fRedraw = TRUE;
  829.     break;
  830.  
  831.     case IDM_DIMENSIONS:
  832.     if (global.fUpdateAttrs && (global.flMiscAttrs & (LFA_XOFF |
  833.         LFA_YOFF | LFA_XSCALE | LFA_YSCALE)))
  834.         MyMessageBox(hwnd, pszAttrs);
  835.     if (WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)DimensionsDlg, NULL,
  836.                IDR_DIMENSIONSDLG, NULL ))
  837.         fRedraw = TRUE;
  838.     break;
  839.  
  840.     case IDM_DRAGDIMS:
  841.     global.fTracking = TRUE;
  842.     break;
  843.  
  844.     /********************************************************************/
  845.  
  846.     case IDM_ATTRREDRAW:
  847.     UPDATE_MENU_BOOL(global.pThrTop->fAttrRedraw, IDM_ATTRREDRAW);
  848.     break;
  849.     }
  850.  
  851.     if (fRedraw)
  852.     if (global.pThrTop->fAttrRedraw)
  853.         return TRUE;
  854.     return FALSE;
  855. }
  856.  
  857.  
  858.  
  859.  
  860. /************************************************************************
  861. *
  862. *   LfEnvironmentMenu
  863. *
  864. *   These commands alter the way a thread reacts to system and program
  865. *   events by toggling certain flags.  Each thread has its own
  866. *   environment flags.
  867. *
  868. ************************************************************************/
  869.  
  870. VOID
  871. LfEnvironmentMenu(hwnd, id)
  872. HWND hwnd;
  873. USHORT id;
  874. {
  875.     switch (id)
  876.     {
  877.     case IDM_AUTORESIZE:
  878.     UPDATE_MENU_BOOL(global.pThrTop->fAutoSizePS, IDM_AUTORESIZE);
  879.     break;
  880.  
  881.     case IDM_AUTOSELECTDIMS:
  882.     UPDATE_MENU_BOOL(global.pThrTop->fAutoSelectDims, IDM_AUTOSELECTDIMS);
  883.     break;
  884.  
  885.     case IDM_CLEARONREDRAW:
  886.     UPDATE_MENU_BOOL(global.pThrTop->fClearOnRedraw, IDM_CLEARONREDRAW);
  887.     break;
  888.  
  889.     case IDM_AUTOSTARTREDRAW:
  890.     UPDATE_MENU_BOOL(global.pThrTop->fAutoStartRedraw, IDM_AUTOSTARTREDRAW);
  891.     if (global.pThrTop->fAutoStartRedraw)
  892.         LfStartRedrawTimer();
  893.     break;
  894.  
  895.     case IDM_COLLECTBOUNDS:
  896.     UPDATE_MENU_BOOL(global.pThrTop->fCollectBounds, IDM_COLLECTBOUNDS);
  897.     break;
  898.  
  899.     }
  900.  
  901.     hwnd;    /* this prevents an "unused variable" warning message */
  902. }
  903.  
  904.  
  905.  
  906.  
  907. /************************************************************************
  908. *
  909. *   LfSelectDimension
  910. *
  911. *   Set the dimensions of the next fractal by dragging a rectangle
  912. *   on the screen.
  913. *
  914. ************************************************************************/
  915.  
  916. VOID
  917. LfSelectDimension(hwnd, pt)
  918. HWND hwnd;
  919. POINTS pt;
  920. {
  921.     TRACKINFO ti;
  922.     LONG lXExt, lYExt;
  923.  
  924.  
  925.     WinSendMsg(global.hwndFrame, WM_QUERYTRACKINFO, (MPARAM)TF_MOVE, (MPARAM)&ti);
  926.  
  927.     ti.cxBorder   = 1;
  928.     ti.cyBorder   = 1;
  929.     ti.rclTrack.xLeft    = (LONG)pt.x;
  930.     ti.rclTrack.yBottom = (LONG)pt.y;
  931.     ti.rclTrack.xRight    = (LONG)pt.x;
  932.     ti.rclTrack.yTop    = (LONG)pt.y;
  933.     ti.fs = TF_RIGHT | TF_TOP;
  934.     ti.ptlMinTrackSize.x = 1L;
  935.     ti.ptlMinTrackSize.y = 1L;
  936.  
  937.     if (WinTrackRect(hwnd, NULL, &ti))
  938.     {
  939.     lXExt = (global.pThrTop->rcl).xRight - (global.pThrTop->rcl).xLeft;
  940.     lYExt = (global.pThrTop->rcl).yTop   - (global.pThrTop->rcl).yBottom;
  941.  
  942.     global.dblXScale = (double)(ti.rclTrack.xRight - ti.rclTrack.xLeft)   / (double)lXExt;
  943.     global.dblYScale = (double)(ti.rclTrack.yTop   - ti.rclTrack.yBottom) / (double)lYExt;
  944.     global.dblXOff     = (double) ti.rclTrack.xLeft    / (double)lXExt;
  945.     global.dblYOff     = (double) ti.rclTrack.yBottom / (double)lYExt;
  946.  
  947.     global.flMiscAttrs |= LFA_XSCALE | LFA_YSCALE | LFA_XOFF | LFA_YOFF;
  948.  
  949.     global.pThrTop->fUpdateAttrs = TRUE;
  950.     global.fUpdateAttrs         = TRUE;
  951.     }
  952. }
  953.  
  954.  
  955.  
  956.  
  957. /************************************************************************
  958. *
  959. *   LfSquareBitmap
  960. *
  961. *   Resize the window horizontally to so that the client area is a
  962. *   square.
  963. *
  964. ************************************************************************/
  965.  
  966. VOID
  967. LfSquareBitmap(hwnd)
  968. HWND hwnd;
  969. {
  970.     SWP swp;
  971.     HWND hwndDesk;
  972.     RECTL rcl;
  973.  
  974.     if (hwnd == global.hwnd)
  975.     if (hwndDesk = WinQueryDesktopWindow(global.hab, NULL))
  976.         if (WinQueryWindowPos(global.hwndFrame, (PSWP)&swp))
  977.         {
  978.         rcl.xLeft   = 0L;
  979.         rcl.yBottom = 0L;
  980.         rcl.xRight  = swp.cx;
  981.         rcl.yTop    = swp.cy;
  982.         if (WinCalcFrameRect(global.hwndFrame, &rcl, TRUE))
  983.         {
  984.             rcl.xRight    = (SHORT)((LONG)rcl.yTop   *
  985.                   global.pThrTop->AspectRatio.lHorz /
  986.                   global.pThrTop->AspectRatio.lVert);
  987.  
  988.             if (WinCalcFrameRect(global.hwndFrame, &rcl, FALSE))
  989.             WinSetWindowPos(global.hwndFrame, 0, swp.x, swp.y,
  990.                 (SHORT)rcl.xRight, (SHORT)rcl.yTop,
  991.                 SWP_SIZE);
  992.         }
  993.         }
  994. }
  995.  
  996.  
  997.  
  998.  
  999. /************************************************************************
  1000. *
  1001. *   LfResizeBitmapToWindow
  1002. *
  1003. *   Resize the bitmap to match the windows dimensions exactly.
  1004. *
  1005. ************************************************************************/
  1006.  
  1007. VOID
  1008. LfResizeBitmapToWindow()
  1009. {
  1010.     global.bm.cx = (USHORT) (global.rcl.xRight - global.rcl.xLeft);
  1011.     global.bm.cy = (USHORT) (global.rcl.yTop   - global.rcl.yBottom);
  1012.     global.bm.cPlanes    = global.pThrTop->cPlanes;
  1013.     global.bm.cBitCount = global.pThrTop->cBitCount;
  1014.  
  1015.     LfResizePS(global.pThrTop);
  1016. }
  1017.  
  1018.  
  1019.  
  1020.  
  1021. /************************************************************************
  1022. *
  1023. *   LfSelect
  1024. *
  1025. *   Select a rectangle to cut or copy to the clipboard.
  1026. *
  1027. ************************************************************************/
  1028.  
  1029. VOID
  1030. LfSelect(hwnd, pt)
  1031. HWND hwnd;
  1032. POINTS pt;
  1033. {
  1034.     HPS hps;
  1035.     TRACKINFO ti;
  1036.     PRECTL prcl;
  1037.  
  1038.  
  1039.     if (global.fShowSelectRc)
  1040.     {
  1041.     global.fShowSelectRc = FALSE;
  1042.     hps = WinGetPS(hwnd);
  1043.     if (global.fTempSelect)
  1044.     {
  1045.         prcl = &global.rclSelect;
  1046.         global.fTempSelect = FALSE;
  1047.     }
  1048.     else
  1049.         prcl = &global.rclCutCopy;
  1050.     LfShowSelectRc(hps, prcl);
  1051.     WinReleasePS(hps);
  1052.     }
  1053.  
  1054.     WinSendMsg(global.hwndFrame, WM_QUERYTRACKINFO, (MPARAM)TF_MOVE, (MPARAM)&ti);
  1055.  
  1056.     ti.cxBorder = 1;
  1057.     ti.cyBorder = 1;
  1058.     ti.rclTrack.xLeft    = (LONG)pt.x;
  1059.     ti.rclTrack.yBottom = (LONG)pt.y;
  1060.     ti.rclTrack.xRight    = (LONG)pt.x;
  1061.     ti.rclTrack.yTop    = (LONG)pt.y;
  1062.     ti.fs = TF_RIGHT | TF_TOP;
  1063.     ti.ptlMinTrackSize.x = 1L;
  1064.     ti.ptlMinTrackSize.y = 1L;
  1065.  
  1066.     if (WinTrackRect(hwnd, NULL, &ti))
  1067.     {
  1068.     global.rclSelect.xLeft     = ti.rclTrack.xLeft;
  1069.     global.rclSelect.yBottom = ti.rclTrack.yBottom;
  1070.     global.rclSelect.xRight  = ti.rclTrack.xRight;
  1071.     global.rclSelect.yTop     = ti.rclTrack.yTop;
  1072.  
  1073.     global.fShowSelectRc = TRUE;
  1074.     global.fTempSelect   = TRUE;
  1075.     hps = WinGetPS(hwnd);
  1076.     LfShowSelectRc(hps, &global.rclSelect);
  1077.     WinReleasePS(hps);
  1078.     }
  1079. }
  1080.  
  1081.  
  1082.  
  1083.  
  1084. /************************************************************************
  1085. *
  1086. *   LfSelectAll
  1087. *
  1088. *   Select the entire surface to cut or copy to the clipboard.
  1089. *
  1090. ************************************************************************/
  1091.  
  1092. VOID
  1093. LfSelectAll(hwnd)
  1094. HWND hwnd;
  1095. {
  1096.     HPS hps;
  1097.  
  1098.     global.rclSelect = global.pThrTop->rcl;
  1099.  
  1100.     global.fShowSelectRc = TRUE;
  1101.     global.fTempSelect     = TRUE;
  1102.     hps = WinGetPS(hwnd);
  1103.     LfShowSelectRc(hps, &global.rclSelect);
  1104.     WinReleasePS(hps);
  1105. }
  1106.  
  1107.  
  1108.  
  1109.  
  1110. /************************************************************************
  1111. *
  1112. *   LfCut
  1113. *
  1114. *   Cuts the selected rectangle from the bitmap and puts it in the
  1115. *   clipboard.
  1116. *
  1117. ************************************************************************/
  1118.  
  1119. VOID
  1120. LfCut(hwnd)
  1121. HWND hwnd;
  1122. {
  1123.     if (LfCopy(hwnd))
  1124.     LfClearRect(global.pThrTop, &global.rclCutCopy);
  1125. }
  1126.  
  1127.  
  1128.  
  1129.  
  1130. /************************************************************************
  1131. *
  1132. *   LfCopy
  1133. *
  1134. *   Copies the selected rectangle from the bitmap the clipboard.
  1135. *
  1136. ************************************************************************/
  1137.  
  1138. BOOL
  1139. LfCopy(hwnd)
  1140. HWND hwnd;
  1141. {
  1142.     HPS hps;
  1143.     PRECTL prcl;
  1144.     SIZEL size;
  1145.     BITMAPINFOHEADER bminfo;
  1146.     POINTL  aptl[4];
  1147.  
  1148.  
  1149.  
  1150.     global.fShowSelectRc = FALSE;
  1151.     hps = WinGetPS(hwnd);
  1152.     if (global.fTempSelect)
  1153.     {
  1154.     prcl = &global.rclSelect;
  1155.     global.fTempSelect = FALSE;
  1156.     }
  1157.     else
  1158.     prcl = &global.rclCutCopy;
  1159.     LfShowSelectRc(hps, prcl);
  1160.     WinReleasePS(hps);
  1161.  
  1162.     if (global.fUseClipbrd)
  1163.     {
  1164.     if (WinOpenClipbrd(global.hab))
  1165.     {
  1166.         global.fHaveSelectRc = TRUE;
  1167.         global.rclCutCopy.xLeft   = global.rclSelect.xLeft;
  1168.         global.rclCutCopy.yBottom = global.rclSelect.yBottom;
  1169.         global.rclCutCopy.xRight  = global.rclSelect.xRight;
  1170.         global.rclCutCopy.yTop    = global.rclSelect.yTop;
  1171.  
  1172.         /* copy bits here */
  1173.  
  1174.         WinCloseClipbrd(global.hab);
  1175.  
  1176.         return TRUE;
  1177.     }
  1178.     }
  1179.     else
  1180.     {
  1181.     global.fHaveSelectRc = TRUE;
  1182.     global.rclCutCopy.xLeft   = global.rclSelect.xLeft;
  1183.     global.rclCutCopy.yBottom = global.rclSelect.yBottom;
  1184.     global.rclCutCopy.xRight  = global.rclSelect.xRight;
  1185.     global.rclCutCopy.yTop      = global.rclSelect.yTop;
  1186.  
  1187.     if (global.fHaveCutCopyDC)
  1188.     {
  1189.         GpiSetBitmap(global.CutCopyPS, NULL);
  1190.         GpiDeleteBitmap(global.CutCopyBM);
  1191.         GpiDestroyPS(global.CutCopyPS);
  1192.         DevCloseDC(global.CutCopyDC);
  1193.         global.fHaveCutCopyDC = FALSE;
  1194.     }
  1195.  
  1196.     global.CutCopyDC = DevOpenDC(global.hab, OD_MEMORY, "*", 0L, NULL, NULL);
  1197.     if (!global.CutCopyDC)
  1198.         return FALSE;
  1199.  
  1200.     size.cx = 0L;
  1201.     size.cy = 0L;
  1202.     global.CutCopyPS = GpiCreatePS(global.hab, global.CutCopyDC, &size,
  1203.                  PU_PELS|GPIT_MICRO|GPIA_ASSOC);
  1204.     if (!global.CutCopyPS)
  1205.         goto lfc_error_close_dc;
  1206.  
  1207.  
  1208.     bminfo.cbFix = sizeof(BITMAPINFOHEADER);
  1209.     bminfo.cx = (USHORT) (global.rclCutCopy.xRight - global.rclCutCopy.xLeft);
  1210.     bminfo.cy = (USHORT) (global.rclCutCopy.yTop   - global.rclCutCopy.yBottom);
  1211.     bminfo.cPlanes     = global.pThrTop->cPlanes;
  1212.     bminfo.cBitCount = global.pThrTop->cBitCount;
  1213.     global.CutCopyBM = GpiCreateBitmap(global.CutCopyPS, &bminfo, 0L, 0L, 0L);
  1214.     if (!global.CutCopyBM)
  1215.         goto lfc_error_destroy_ps;
  1216.     GpiSetBitmap(global.CutCopyPS, global.CutCopyBM);
  1217.  
  1218.     aptl[0].x = 0L;
  1219.     aptl[0].y = 0L;
  1220.     aptl[1].x = global.rclCutCopy.xRight - global.rclCutCopy.xLeft;
  1221.     aptl[1].y = global.rclCutCopy.yTop   - global.rclCutCopy.yBottom;
  1222.     aptl[2].x = global.rclCutCopy.xLeft;
  1223.     aptl[2].y = global.rclCutCopy.yBottom;
  1224.  
  1225.     GpiBitBlt(global.CutCopyPS, global.pThrTop->hps, 3L, aptl, ROP_SRCCOPY, NULL);
  1226.  
  1227.     global.fHaveCutCopyDC = TRUE;
  1228.     return TRUE;
  1229.  
  1230.  
  1231. lfc_error_destroy_ps:
  1232.     GpiDestroyPS(global.CutCopyPS);
  1233. lfc_error_close_dc:
  1234.     DevCloseDC(global.CutCopyDC);
  1235.     return FALSE;
  1236.     }
  1237.  
  1238.     return FALSE;
  1239. }
  1240.  
  1241.  
  1242.  
  1243.  
  1244. /************************************************************************
  1245. *
  1246. *   LfPaste
  1247. *
  1248. *   Pastes the selected rectangle from the clipboard to the bitmap.
  1249. *   Hides the selection rectangle before calling WinTrackRect.
  1250. *
  1251. ************************************************************************/
  1252.  
  1253. VOID
  1254. LfPaste(hwnd)
  1255. HWND hwnd;
  1256. {
  1257.     HPS hps;
  1258.     PRECTL prcl;
  1259.     TRACKINFO ti;
  1260.     POINTL    aptl[4];
  1261.  
  1262.  
  1263.     if (global.fShowSelectRc)
  1264.     {
  1265.     global.fShowSelectRc = FALSE;
  1266.     hps = WinGetPS(hwnd);
  1267.     if (global.fTempSelect)
  1268.     {
  1269.         prcl = &global.rclSelect;
  1270.         global.fTempSelect = FALSE;
  1271.     }
  1272.     else
  1273.         prcl = &global.rclCutCopy;
  1274.     LfShowSelectRc(hps, prcl);
  1275.     WinReleasePS(hps);
  1276.     }
  1277.  
  1278.     WinSendMsg(global.hwndFrame, WM_QUERYTRACKINFO, (MPARAM)TF_MOVE, (MPARAM)&ti);
  1279.  
  1280.     ti.cxBorder = 1;
  1281.     ti.cyBorder = 1;
  1282.     ti.rclTrack.xLeft    = global.rclCutCopy.xLeft;
  1283.     ti.rclTrack.yBottom = global.rclCutCopy.yBottom;
  1284.     ti.rclTrack.xRight    = global.rclCutCopy.xRight;
  1285.     ti.rclTrack.yTop    = global.rclCutCopy.yTop;
  1286.     ti.fs = TF_MOVE;
  1287.     ti.ptlMinTrackSize.x = 1L;
  1288.     ti.ptlMinTrackSize.y = 1L;
  1289.  
  1290.     if (WinTrackRect(hwnd, NULL, &ti))
  1291.     {
  1292.     if (global.fUseClipbrd)
  1293.     {
  1294.         if (WinOpenClipbrd(global.hab))
  1295.         {
  1296.         /* copy bits here */
  1297.         WinCloseClipbrd(global.hab);
  1298.         }
  1299.     }
  1300.     else
  1301.     {
  1302.         aptl[0].x = ti.rclTrack.xLeft;
  1303.         aptl[0].y = ti.rclTrack.yBottom;
  1304.         aptl[1].x = ti.rclTrack.xLeft   + (global.rclCutCopy.xRight - global.rclCutCopy.xLeft);
  1305.         aptl[1].y = ti.rclTrack.yBottom + (global.rclCutCopy.yTop    - global.rclCutCopy.yBottom);
  1306.         aptl[2].x = 0L;
  1307.         aptl[2].y = 0L;
  1308.  
  1309.         GpiBitBlt(global.pThrTop->hps, global.CutCopyPS, 3L, aptl, global.ulPasteROP, NULL);
  1310.         WinInvalidateRect(global.hwnd, &(ti.rclTrack), FALSE);
  1311.     }
  1312.     }
  1313. }
  1314.  
  1315.  
  1316.  
  1317.  
  1318. /************************************************************************
  1319. *
  1320. *   LfSelectXform
  1321. *
  1322. *   Select a similarity transform.
  1323. *
  1324. ************************************************************************/
  1325.  
  1326. VOID
  1327. LfSelectXform(hwnd, pthr, id)
  1328. HWND hwnd;
  1329. PTHR pthr;
  1330. USHORT id;
  1331. {
  1332.     BOOL fAlreadySaidIt = FALSE;
  1333.  
  1334.  
  1335.     if ((id != pthr->usCurXform) ||
  1336.        ((id != global.usCurXform) && global.fUpdateAttrs))
  1337.     {
  1338.     if (global.fUpdateAttrs && (global.flMiscAttrs & LFA_CURXFORM))
  1339.     {
  1340.         MyMessageBox(hwnd, pszAttrs);
  1341.         fAlreadySaidIt = TRUE;
  1342.     }
  1343.  
  1344.     global.flMiscAttrs |= LFA_CURXFORM;
  1345.  
  1346.     if (LfIsThreadTop(pthr))
  1347.     {
  1348.         if (fAlreadySaidIt)
  1349.         UNCHECK_MENU_ITEM(global.hwndFrame, global.usCurXform);
  1350.         else
  1351.         UNCHECK_MENU_ITEM(global.hwndFrame, pthr->usCurXform);
  1352.         global.usCurXform = id;
  1353.         CHECK_MENU_ITEM(global.hwndFrame, id);
  1354.     }
  1355.     else
  1356.         global.usCurXform = id;
  1357.  
  1358.     pthr->fUpdateAttrs  = TRUE;
  1359.     global.fUpdateAttrs = TRUE;
  1360.     }
  1361.  
  1362.     if (pthr->fAutoSelectDims)
  1363.     {
  1364.     if (global.fUpdateAttrs && (global.flMiscAttrs & (LFA_XSCALE |
  1365.          LFA_YSCALE | LFA_XOFF | LFA_YOFF | LFA_POLYGONSIDES)))
  1366.         if (!fAlreadySaidIt)
  1367.         MyMessageBox(hwnd, pszAttrs);
  1368.  
  1369.     global.dblXScale      = aXform[id - IDM_SHARKTOOTH].xScale;
  1370.     global.dblYScale      = aXform[id - IDM_SHARKTOOTH].yScale;
  1371.     global.dblXOff          = aXform[id - IDM_SHARKTOOTH].xOff;
  1372.     global.dblYOff          = aXform[id - IDM_SHARKTOOTH].yOff;
  1373.     global.usPolygonSides = aXform[id - IDM_SHARKTOOTH].usSides;
  1374.  
  1375.     global.flMiscAttrs |= LFA_XSCALE | LFA_YSCALE | LFA_XOFF | LFA_YOFF |
  1376.                   LFA_POLYGONSIDES;
  1377.     pthr->fUpdateAttrs  = TRUE;
  1378.     global.fUpdateAttrs = TRUE;
  1379.     }
  1380. }
  1381.  
  1382.  
  1383.  
  1384.  
  1385. /************************************************************************
  1386. *
  1387. *   LfSelectPrim
  1388. *
  1389. *   Select a drawing primitive.
  1390. *
  1391. ************************************************************************/
  1392.  
  1393. VOID
  1394. LfSelectPrim(hwnd, pthr, id)
  1395. HWND hwnd;
  1396. PTHR pthr;
  1397. USHORT id;
  1398. {
  1399.     BOOL fAlreadySaidIt = FALSE;
  1400.  
  1401.  
  1402.     if ((id != pthr->usCurPrim) ||
  1403.        ((id != global.usCurPrim) && global.fUpdateAttrs))
  1404.     {
  1405.     if (global.fUpdateAttrs && (global.flMiscAttrs & LFA_CURPRIM))
  1406.     {
  1407.         MyMessageBox(hwnd, "Previous attributes not read yet.");
  1408.         fAlreadySaidIt = TRUE;
  1409.     }
  1410.  
  1411.     if (LfIsThreadTop(pthr))
  1412.     {
  1413.         if (fAlreadySaidIt)
  1414.         UNCHECK_MENU_ITEM(global.hwndFrame, global.usCurPrim);
  1415.         else
  1416.         UNCHECK_MENU_ITEM(global.hwndFrame, pthr->usCurPrim);
  1417.         global.usCurPrim = id;
  1418.         CHECK_MENU_ITEM(global.hwndFrame, id);
  1419.     }
  1420.     else
  1421.         global.usCurPrim = id;
  1422.  
  1423.     global.flMiscAttrs |= LFA_CURPRIM;
  1424.     pthr->fUpdateAttrs  = TRUE;
  1425.     global.fUpdateAttrs = TRUE;
  1426.     }
  1427. }
  1428.